@@ -4,9 +4,10 @@ from django.conf import settings  | 
            ||
| 4 | 4 | 
                from django_logit import logit  | 
            
| 5 | 5 | 
                from django_response import response  | 
            
| 6 | 6 | 
                 | 
            
| 7 | 
                -from kodo.decorators import check_admin  | 
            |
| 8 | 
                -from apps.lensman.activity.models import LensmanContributionActivityIncomeExpensesInfo  | 
            |
| 9 | 7 | 
                from account.models import LensmanInfo  | 
            
| 8 | 
                +from apps.lensman.activity.models import LensmanContributionActivityIncomeExpensesInfo  | 
            |
| 9 | 
                +from kodo.decorators import check_admin  | 
            |
| 10 | 
                +  | 
            |
| 10 | 11 | 
                 | 
            
| 11 | 12 | 
                @logit(res=True)  | 
            
| 12 | 13 | 
                @check_admin  | 
            
                @@ -21,4 +22,4 @@ def add_lensman_contribution_income_api(request, administrator):  | 
            ||
| 21 | 22 | 
                 | 
            
| 22 | 23 | 
                     LensmanContributionActivityIncomeExpensesInfo.objects.update_or_create(contribution_id=contribution_id, lensman_id=lensman.lensman_id, activity_id=activity_id, user_id=user_id, defaults={'amount': amount})
               | 
            
| 23 | 24 | 
                 | 
            
| 24 | 
                - return response(200, '增加摄影师投稿收入成功')  | 
            |
| 25 | 
                + return response(200, '增加摄影师投稿收入成功')  | 
            
                @@ -4,8 +4,8 @@ from django.conf import settings  | 
            ||
| 4 | 4 | 
                from django_logit import logit  | 
            
| 5 | 5 | 
                from django_response import response  | 
            
| 6 | 6 | 
                 | 
            
| 7 | 
                -from kodo.decorators import check_admin  | 
            |
| 8 | 7 | 
                from apps.contract.models import LensmanContributionContractInfo  | 
            
| 8 | 
                +from kodo.decorators import check_admin  | 
            |
| 9 | 9 | 
                 | 
            
| 10 | 10 | 
                 | 
            
| 11 | 11 | 
                @logit(res=True)  | 
            
                @@ -16,7 +16,7 @@ def get_signed_contribtion_contract_file_api(request, administrator):  | 
            ||
| 16 | 16 | 
                 | 
            
| 17 | 17 | 
                contract = LensmanContributionContractInfo.objects.filter(contribution_id=contribution_id, user_id=user_id).first()  | 
            
| 18 | 18 | 
                 | 
            
| 19 | 
                -    operator =  {
               | 
            |
| 19 | 
                +    operator = {
               | 
            |
| 20 | 20 | 
                "UserId": settings.CONTRACT_LENSMAN_CONTRIBUTION_OPERATOR_ID  | 
            
| 21 | 21 | 
                }  | 
            
| 22 | 22 | 
                 | 
            
                @@ -1,6 +1,7 @@  | 
            ||
| 1 | 1 | 
                # -*- coding: utf-8 -*-  | 
            
| 2 | 2 | 
                 | 
            
| 3 | 3 | 
                import base64  | 
            
| 4 | 
                +import json  | 
            |
| 4 | 5 | 
                 | 
            
| 5 | 6 | 
                import requests  | 
            
| 6 | 7 | 
                from django_logit import logit  | 
            
                @@ -12,7 +13,7 @@ from apps.contract.models import LensmanContributionContractInfo  | 
            ||
| 12 | 13 | 
                from apps.lensman.activity.models import LensmanContributionActivityIncomeExpensesInfo  | 
            
| 13 | 14 | 
                from member.models import MemberActivityContributionInfo  | 
            
| 14 | 15 | 
                from utils.redis.rimage import get_images_data  | 
            
| 15 | 
                -from utils.tencentcloud.ess import (create_document, create_flow, create_scheme_url, start_flow,  | 
            |
| 16 | 
                +from utils.tencentcloud.ess import (callback_decode, create_document, create_flow, create_scheme_url, start_flow,  | 
            |
| 16 | 17 | 
                test_upload_document_files, upload_document_files)  | 
            
| 17 | 18 | 
                 | 
            
| 18 | 19 | 
                 | 
            
                @@ -181,4 +182,16 @@ def get_contribtion_contract_sign_mppath(lensman, FlowId):  | 
            ||
| 181 | 182 | 
                 | 
            
| 182 | 183 | 
                @logit(body=True, res=True)  | 
            
| 183 | 184 | 
                def ess_callback(request):  | 
            
| 185 | 
                +    # curl http://127.0.0.1:8888/api/mp/ess/callback -H 'Content-type: application/json' -X POST -d '{"encrypt":"62KE4r5Wz0yHzEpMOwVRbM1KV0"}'
               | 
            |
| 186 | 
                + data = json.loads(request.body)  | 
            |
| 187 | 
                + data = callback_decode(data['encrypt'])  | 
            |
| 188 | 
                +    MsgType = data.get('MsgType')
               | 
            |
| 189 | 
                + if MsgType == 'FlowStatusChange':  | 
            |
| 190 | 
                +        MsgData = data.get('MsgData', {})
               | 
            |
| 191 | 
                +        FlowId = MsgData.get('FlowId')
               | 
            |
| 192 | 
                +        # DocumentId = MsgData.get('DocumentId')
               | 
            |
| 193 | 
                +        FlowCallbackStatus = MsgData.get('FlowCallbackStatus', -1)
               | 
            |
| 194 | 
                +        Approvers = MsgData.get('Approvers') or [{}]
               | 
            |
| 195 | 
                +        ApproveCallbackStatus = Approvers[-1].get('ApproveCallbackStatus', -1)
               | 
            |
| 196 | 
                + LensmanContributionContractInfo.objects.filter(flow_id=FlowId).update(tencent_contract_status=FlowCallbackStatus, tencent_approve_status=ApproveCallbackStatus)  | 
            |
| 184 | 197 | 
                return response()  | 
            
                @@ -1,3 +1,13 @@  | 
            ||
| 1 | 
                +# -*- coding: utf-8 -*-  | 
            |
| 2 | 
                +  | 
            |
| 1 | 3 | 
                from django.contrib import admin  | 
            
| 2 | 4 | 
                 | 
            
| 3 | 
                -# Register your models here.  | 
            |
| 5 | 
                +from apps.contract.models import LensmanContributionContractInfo  | 
            |
| 6 | 
                +  | 
            |
| 7 | 
                +  | 
            |
| 8 | 
                +class LensmanContributionContractInfoAdmin(admin.ModelAdmin):  | 
            |
| 9 | 
                +    list_display = ('contract_id', 'user_id', 'lensman_id', 'activity_id', 'contribution_id', 'flow_id', 'document_id', 'tencent_contract_status', 'tencent_approve_status', 'status', 'created_at', 'updated_at')
               | 
            |
| 10 | 
                +    list_filter = ('brand_id', 'coupon_expire_type', 'status')
               | 
            |
| 11 | 
                +  | 
            |
| 12 | 
                +  | 
            |
| 13 | 
                +admin.site.register(LensmanContributionContractInfo, LensmanContributionContractInfoAdmin)  | 
            
                @@ -1,4 +1,5 @@  | 
            ||
| 1 | 1 | 
                # -*- coding: utf-8 -*-  | 
            
| 2 | 
                +  | 
            |
| 2 | 3 | 
                from django.db import models  | 
            
| 3 | 4 | 
                from django.utils.translation import ugettext_lazy as _  | 
            
| 4 | 5 | 
                from django_models_ext import BaseModelMixin, upload_file_path, upload_path  | 
            
                @@ -8,8 +9,6 @@ from TimeConvert import TimeConvert as tc  | 
            ||
| 8 | 9 | 
                 | 
            
| 9 | 10 | 
                from utils.qiniucdn import qiniu_file_url  | 
            
| 10 | 11 | 
                 | 
            
| 11 | 
                -# Create your models here.  | 
            |
| 12 | 
                -  | 
            |
| 13 | 12 | 
                 | 
            
| 14 | 13 | 
                class LensmanContributionContractInfo(BaseModelMixin):  | 
            
| 15 | 14 | 
                CONTRACT_STATUS_TUPLE = (  | 
            
                @@ -67,13 +66,14 @@ class LensmanContributionContractInfo(BaseModelMixin):  | 
            ||
| 67 | 66 | 
                @property  | 
            
| 68 | 67 | 
                def contract_file_url(self):  | 
            
| 69 | 68 | 
                return qiniu_file_url(self.contract_file.name, bucket='tamron')  | 
            
| 70 | 
                -  | 
            |
| 69 | 
                +  | 
            |
| 71 | 70 | 
                @property  | 
            
| 72 | 71 | 
                def contract_status(self):  | 
            
| 73 | 72 | 
                if(self.tencent_approve_status == 3 and self.tencent_contract_status == 4):  | 
            
| 74 | 73 | 
                return 1  | 
            
| 75 | 74 | 
                else:  | 
            
| 76 | 75 | 
                return 0  | 
            
| 76 | 
                +  | 
            |
| 77 | 77 | 
                @property  | 
            
| 78 | 78 | 
                def data(self):  | 
            
| 79 | 79 | 
                         return {
               | 
            
                @@ -248,8 +248,8 @@ TENCENTCLOUD = {
               | 
            ||
| 248 | 248 | 
                'template_id': '',  | 
            
| 249 | 249 | 
                'secret_id': '',  | 
            
| 250 | 250 | 
                'secret_key': '',  | 
            
| 251 | 
                - 'callback_secret_id': '',  | 
            |
| 252 | 251 | 
                'callback_secret_key': '',  | 
            
| 252 | 
                + 'callback_secret_token': '',  | 
            |
| 253 | 253 | 
                'endpoint': 'ess.tencentcloudapi.com',  | 
            
| 254 | 254 | 
                'file_endpoint': 'file.ess.tencent.cn',  | 
            
| 255 | 255 | 
                },  | 
            
                @@ -9,6 +9,7 @@ mock==4.0.3  | 
            ||
| 9 | 9 | 
                monetary==1.0.3  | 
            
| 10 | 10 | 
                mysqlclient==2.1.1  | 
            
| 11 | 11 | 
                pngquant==1.0.8  | 
            
| 12 | 
                +pycryptodomex==3.20.0  | 
            |
| 12 | 13 | 
                pysnippets==1.1.4  | 
            
| 13 | 14 | 
                pyzbar==0.1.9  | 
            
| 14 | 15 | 
                qiniu==7.9.0  | 
            
                @@ -1,7 +1,9 @@  | 
            ||
| 1 | 1 | 
                # -*- coding: utf-8 -*-  | 
            
| 2 | 2 | 
                 | 
            
| 3 | 
                +import base64  | 
            |
| 3 | 4 | 
                import json  | 
            
| 4 | 5 | 
                 | 
            
| 6 | 
                +from Cryptodome.Cipher import AES  | 
            |
| 5 | 7 | 
                from django.conf import settings  | 
            
| 6 | 8 | 
                from tencentcloud.common import credential  | 
            
| 7 | 9 | 
                from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException  | 
            
                @@ -16,8 +18,8 @@ operator_id = tencentcloud_cfg.get('operator_id')
               | 
            ||
| 16 | 18 | 
                 template_id = tencentcloud_cfg.get('template_id')
               | 
            
| 17 | 19 | 
                 secret_id = tencentcloud_cfg.get('secret_id')
               | 
            
| 18 | 20 | 
                 secret_key = tencentcloud_cfg.get('secret_key')
               | 
            
| 19 | 
                -callback_secret_id = tencentcloud_cfg.get('callback_secret_id')
               | 
            |
| 20 | 21 | 
                 callback_secret_key = tencentcloud_cfg.get('callback_secret_key')
               | 
            
| 22 | 
                +callback_secret_token = tencentcloud_cfg.get('callback_secret_token')
               | 
            |
| 21 | 23 | 
                 endpoint = tencentcloud_cfg.get('endpoint')
               | 
            
| 22 | 24 | 
                 file_endpoint = tencentcloud_cfg.get('file_endpoint')
               | 
            
| 23 | 25 | 
                 | 
            
                @@ -304,3 +306,32 @@ def create_scheme_url(flow_id=None, name=None, mobile=None, card_type='ID_CARD',  | 
            ||
| 304 | 306 | 
                         resp = {}
               | 
            
| 305 | 307 | 
                 | 
            
| 306 | 308 | 
                return resp  | 
            
| 309 | 
                +  | 
            |
| 310 | 
                +  | 
            |
| 311 | 
                +def decode_aes256(data, encryption_key):  | 
            |
| 312 | 
                + iv = encryption_key[0:16]  | 
            |
| 313 | 
                + aes = AES.new(encryption_key, AES.MODE_CBC, iv)  | 
            |
| 314 | 
                + d = aes.decrypt(data)  | 
            |
| 315 | 
                + unpad = lambda s: s[0:-ord(d[-1:])]  | 
            |
| 316 | 
                + return unpad(d)  | 
            |
| 317 | 
                +  | 
            |
| 318 | 
                +  | 
            |
| 319 | 
                +def test_decode():  | 
            |
| 320 | 
                + # https://qian.tencent.com/developers/company/callback_types_v2  | 
            |
| 321 | 
                + data = "62KE4r5Wz0yHzEpMOwVRbM1KV0pPjj+cmJkT+i65MMscgfHAdNP+9K0nV/fFw1xriwi08APc/wM0mHprE43Hc91VPhRDnu2Wn0+bjzgjmy/FgZKZATR9oquy0/BCWu4C77AjkpkoU1/E7gGLr8M9u9t7zbS4AkkGK5xL5TtwI0sS+CMygmyV7bRjxebMycI52U3QJiwDRIPxFO+7yqeXYXV9AQrRskpCDBNFGW72bh+Ixw9dtX00kWcwVQ93V+mayrvdQ8oGSsL32m72kbBfahsIvIxSYSdDAEeTyokqKGfaLWD27vm55QG218IFKEsOJFDGdqCF+IBcM/+rOFeOrewvP5ehIO2KjFBecTDn0RQTlIiokXIQ4zJKvu6njePFRFoFCZjd4oiEIVn/OBw+rjXml3qwgVBQjPRtYdvDJFNENlVjlkVVmLWeS8MIdqsFWhm6Sa7O8X57mwc0cLJ22mGbyVEzNTFqeFJ/mkueW0leLcoZdjv/+IxZusqa1cpfwzkZhwi5rY6kJffNkkrxIc6OeRvpU4ECgBe/b+kxX+ObC0z9u7nzoZAOHx4akYviyIU5B1romjdfHQ/wDr5udm4Rl4NBhU/6V06Rvaadw0Ta9oBkZHGNxFWv32MnL7fVA0zVNOFDP8n+kaQiNGFAXLF4F5oIItYc5+Gp/IxfkltEki7ni7LztViE7b/ZiKSM+gzQn6fLsJ/dlUoZmh141Y0V/GPpsbxBOnWCjBZdNkLTKxdKCMScLCTysJxv7l6Swff8nAEurbzx1tvyhJAvUDnIaLyP8pRPRFq8p0xm3ZVpOo9k7A952XxVHSs40g4sr/Dihkn60aVhGtKK9DueCzn8P3cWG4TYc03M1hNlPfF+UAfnvQ1ZYAMKT/XPLqYtgRFpRkK96YfVecIrfUe9MjWl0/g4hYCAAOJurFoeGwkJiyQ8Q7DCI5EaHa3s/vI621yQyytC6D2u86RiDJxMW0PdvkUfayT7iPwC83EsfEzpQXr0yeSCQCSBgNByEuCNnZl8LAhYl05Y9+bgCzSPt6EUvmaXclYL+/EPrEmi+hzIdXUwBfhXgICT8MteJgMSgmJM2FjjGxy6uZtfHKRIzf1wk6OORPkPJtMgjlMtMs6VFC62EEeo5Xy2v1S95WT/WQ0tnGR8KjbNnmjNSRyD8VtS2mjlLXaK0xRb71YGt57O19YxQQ3R/Hq9zGqOjG+Agdl+pcvh47RlF8o3CnlU7Q=="  | 
            |
| 322 | 
                + encryption_key = 'TencentEssEncryptTestKey12345678'  | 
            |
| 323 | 
                + return callback_decode(data, encryption_key)  | 
            |
| 324 | 
                +  | 
            |
| 325 | 
                +  | 
            |
| 326 | 
                +def callback_decode(data, encryption_key=None):  | 
            |
| 327 | 
                +    # 此处传入密文,如果接收到的数据是{"encrypt":"base64后的密文"}
               | 
            |
| 328 | 
                + # data = 'base64后的密文'  | 
            |
| 329 | 
                + data = base64.b64decode(data)  | 
            |
| 330 | 
                + encryption_key = encryption_key or callback_secret_key  | 
            |
| 331 | 
                + # encryption_key = bytes(encryption_key or callback_secret_key, encoding="utf8")  | 
            |
| 332 | 
                + # 此处传入CallbackUrlKey  | 
            |
| 333 | 
                + e = decode_aes256(data, encryption_key)  | 
            |
| 334 | 
                + # print(type(e))  | 
            |
| 335 | 
                + # print(e)  | 
            |
| 336 | 
                + # print(str(e, encoding="utf8"))  | 
            |
| 337 | 
                + return json.loads(e)  |